package com.wsoft.bpm.bean;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.extern.log4j.Log4j2;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Optional;

/**
 * 动态审批链路
 *
 * @Author zhonglj
 * @Date 2025/2/17 14:11
 */
@Data
@Log4j2
public class DynamicApprovalChain implements Serializable {
    private static final long serialVersionUID = 1L;

    @Schema(description = "动态流程节点列表")
    private ArrayList<ApprovalChainNode> nodes;
    @Schema(description = "当前节点索引")
    private int currentIndex = -1;

    /**
     * 构建动态审批链
     *
     * @param nodes 动态流程节点列表
     * @return com.wsoft.bpm.bean.DynamicApprovalChain
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public static DynamicApprovalChain build(ArrayList<ApprovalChainNode> nodes) {
        DynamicApprovalChain chain = new DynamicApprovalChain();
        chain.setNodes(nodes);
        // 更新会签
        chain.updateCountersign();
        return chain;
    }

    /**
     * 获取当前节点
     *
     * @return com.wsoft.bpm.bean.ParallelApprovalNode
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public ApprovalChainNode getCurrentNode() {
        return nodes.get(currentIndex);
    }

    /**
     * 是否还有下一个节点
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean hasNextNode() {
        return currentIndex + 1 < nodes.size();
    }

    /**
     * 是否还有上一个节点
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean hasPreNode() {
        return currentIndex - 1 >= 0;
    }

    /**
     * 获取下一个节点
     *
     * @return com.wsoft.bpm.bean.ParallelApprovalNode
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public ApprovalChainNode nextNode() {
        if (hasNextNode()) {
            return nodes.get(++currentIndex);
        } else {
            currentIndex = nodes.size();
            return null;
        }
    }

    /**
     * 获取上一个节点
     *
     * @return com.wsoft.bpm.bean.ParallelApprovalNode
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public ApprovalChainNode preNode() {
        if (hasPreNode()) {
            return nodes.get(--currentIndex);
        } else {
            currentIndex = -1;
            return null;
        }
    }

    /**
     * 重置动态审批链
     *
     * @param newNodes
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean resetChain(ArrayList<ApprovalChainNode> newNodes) {
        if (CollUtil.isEmpty(nodes)) {
            return false;
        }

        if (isRunning()) {
            String currentBusinessId = nodes.get(currentIndex).getBusinessId();
            Optional<ApprovalChainNode> find = newNodes.stream()
                    .filter(newNode -> newNode.getBusinessId().equals(currentBusinessId))
                    .findFirst();
            if (find.isPresent()) {
                ApprovalChainNode currentNewNode = find.get();
                // 更新动态审批节点列表
                nodes = newNodes;
                // 更新当前审批节点索引
                currentIndex = newNodes.indexOf(currentNewNode);
                // 更新会签
                updateCountersign();
                return true;

            } else {
                log.error("已经开始审批，但是当前审批节点在新动态列表中不存在，不允许");
                return false;
            }

        } else if (isEnded()) {
            log.error("已经结束审批，不允许");
            return false;
        }

        return false;
    }

    /**
     * 销毁动态审批链
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean destroyChain() {
        if (isRunning()) {
            return false;
        }

        // 设置对象不可达
        nodes = null;
        currentIndex = -1;
        return true;
    }

    /**
     * 是否正在审批中
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean isRunning() {
        return currentIndex >= 0 && currentIndex < nodes.size();
    }

    /**
     * 是否已经结束
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean isEnded() {
        return currentIndex >= nodes.size();
    }

    /**
     * 更新会签配置
     *
     * @return boolean
     * @author zhonglj
     * @date 2025/2/17 14:54
     **/
    public boolean updateCountersign() {
        if (CollUtil.isEmpty(nodes)) {
            return false;
        }

        for (ApprovalChainNode node : nodes) {
            CountersignElement countersignElement = node.getCountersignElement();
            if (countersignElement == null) {
                if (StrUtil.isNotBlank(node.getCountersignExpression())) {
                    CountersignElement countersign = new CountersignElement();
                    countersign.setTotal(CollUtil.size(node.getAssignList()));
                    countersign.setCompletionExpression(node.getCountersignExpression());
                    node.setCountersignElement(countersign);

                } else {
                    // 否则清空会签元素
                    node.setCountersignElement(null);
                }

            } else {
                // 已经存在会签，更新
                countersignElement.setTotal(CollUtil.size(node.getAssignList()));
                countersignElement.setCompletionExpression(node.getCountersignExpression());
            }

        }

        return true;
    }


    /**
     * 判断传递的节点是否已经审批过
     *
     * @param node
     * @return boolean
     * @author zhonglj
     * @date 2025/3/11 9:29
     **/
    public boolean approved(ApprovalChainNode node) {
        if (CollUtil.isEmpty(nodes)) {
            return false;
        }

        int index = nodes.indexOf(node);
        if (index <= currentIndex) {
            return true;
        }

        return false;
    }

}
